home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\WINTERM.C < prev    next >
C/C++ Source or Header  |  1995-01-09  |  28KB  |  1,234 lines

  1. #include "irc.h"
  2. #include "window.h"
  3. #include "screen.h"
  4. #include "keys.h"
  5. #include "vars.h"
  6. #include <toolhelp.h>
  7.  
  8. #define    TIMER_MINUTE    1
  9. #define    TIMER_SECOND    2
  10.  
  11. extern    time_t    TimerTimeout();
  12.  
  13. static    HFONT    FAR hfontFixed[4];
  14. static    COLORREF FAR acrColours[4][2];
  15. static    int    cxChar;
  16. static    int    cyChar;
  17.  
  18. static    HWND    hwndMain = 0;
  19. static    HWND    hwndMDI = 0;
  20. static    HINSTANCE hInstance = 0;
  21. static    WNDPROC    old_edit_window_proc = 0;
  22.  
  23. static    fd_set    fdsBusy = { 0 };
  24. static    fd_set    fdsDCC = { 0 };
  25. static    fd_set    fdsServer = { 0 };
  26. static    fd_set    fdsDCCWrite = { 0 };
  27.  
  28. static    char    *pchPath = 0;
  29.  
  30. #define    WM_SOCKET    (WM_USER + 100)
  31.  
  32. #define    AT_USCORE    1
  33. #define    AT_BOLD        2
  34. #define    AT_INVERSE    4
  35. #define    AT_STATUS    8
  36.  
  37. #define    AT_FONTFLAGS    3
  38. #define    AT_COLOURFLAGS    12
  39. #define    AT_COLOURSHIFT    2
  40.  
  41. typedef struct    TermLineStru
  42. {
  43.     char    *pchText;
  44.     char    *pchAttribs;
  45. } TermLine;
  46.  
  47. char    far * far winsock_errors[] =
  48. {
  49.     "no error",                    /* 10000 */
  50.     "(Unknown Error)",                /* 10001 */
  51.     "(Unknown Error)",                /* 10002 */
  52.     "(Unknown Error)",                /* 10003 */
  53.     "call cancelled",                /* 10004 */
  54.     "(Unknown Error)",                /* 10005 */
  55.     "(Unknown Error)",                /* 10006 */
  56.     "(Unknown Error)",                /* 10007 */
  57.     "(Unknown Error)",                /* 10008 */
  58.     "bad socket number",                /* 10009 */
  59.     "(Unknown Error)",                /* 10010 */
  60.     "(Unknown Error)",                /* 10011 */
  61.     "(Unknown Error)",                /* 10012 */
  62.     "permission denied",                /* 10013 */
  63.     "fault in WinSock call",            /* 10014 */
  64.     "(Unknown Error)",                /* 10015 */
  65.     "(Unknown Error)",                /* 10016 */
  66.     "(Unknown Error)",                /* 10017 */
  67.     "(Unknown Error)",                /* 10018 */
  68.     "(Unknown Error)",                /* 10019 */
  69.     "(Unknown Error)",                /* 10020 */
  70.     "(Unknown Error)",                /* 10021 */
  71.     "invalid argument to WinSock call",        /* 10022 */
  72.     "(Unknown Error)",                /* 10023 */
  73.     "No more sockets",                /* 10024 */
  74.     "(Unknown Error)",                /* 10025 */
  75.     "(Unknown Error)",                /* 10026 */
  76.     "(Unknown Error)",                /* 10027 */
  77.     "(Unknown Error)",                /* 10028 */
  78.     "(Unknown Error)",                /* 10029 */
  79.     "(Unknown Error)",                /* 10030 */
  80.     "(Unknown Error)",                /* 10031 */
  81.     "(Unknown Error)",                /* 10032 */
  82.     "(Unknown Error)",                /* 10033 */
  83.     "(Unknown Error)",                /* 10034 */
  84.     "operation would block",            /* 10035 */
  85.     "blocking operation in progress",        /* 10036 */
  86.     "already connected",                /* 10037 */
  87.     "socket operation on non socket",        /* 10038 */
  88.     "detstination address required",        /* 10039 */
  89.     "message too long",                /* 10040 */
  90.     "protocol wrong type for socket",        /* 10041 */
  91.     "protocol not available",            /* 10042 */
  92.     "protocol not supported",            /* 10043 */
  93.     "socket type not supported",            /* 10044 */
  94.     "operation not supported on a socket",        /* 10045 */
  95.     "protocol family not supported",        /* 10046 */
  96.     "address family not supported",            /* 10047 */
  97.     "address already in use",            /* 10048 */
  98.     "can't assign requested address",        /* 10049 */
  99.     "network is down",                /* 10050 */
  100.     "network is unreachable",            /* 10051 */
  101.     "network dropped connection on reset",        /* 10052 */
  102.     "software caused connection abort",        /* 10053 */
  103.     "connection reset by peer",            /* 10054 */
  104.     "no buffer space available",            /* 10055 */
  105.     "socket is already connected",            /* 10056 */
  106.     "socket is not connected",            /* 10057 */
  107.     "can't send after socket shutdown",        /* 10058 */
  108.     "too many references: can't splice",        /* 10059 */
  109.     "connection timed out",                /* 10060 */
  110.     "connection refused",                /* 10061 */
  111.     "too many levels of symbolic links",        /* 10062 */
  112.     "file name too long",                /* 10063 */
  113.     "host is down",                    /* 10064 */
  114.     "no route to host",                /* 10065 */
  115.     "directory not empty",                /* 10066 */
  116.     "too many processes",                /* 10067 */
  117.     "too many users",                /* 10068 */
  118.     "disk quota exceeded",                /* 10069 */
  119.     "stale NFS file handle",            /* 10070 */
  120.     "too many levels of remote in path",        /* 10071 */
  121.     "(Unknown Error)",                /* 10072 */
  122.     "(Unknown Error)",                /* 10073 */
  123.     "(Unknown Error)",                /* 10074 */
  124.     "(Unknown Error)",                /* 10075 */
  125.     "(Unknown Error)",                /* 10076 */
  126.     "(Unknown Error)",                /* 10077 */
  127.     "(Unknown Error)",                /* 10078 */
  128.     "(Unknown Error)",                /* 10079 */
  129.     "(Unknown Error)",                /* 10080 */
  130.     "(Unknown Error)",                /* 10081 */
  131.     "(Unknown Error)",                /* 10082 */
  132.     "(Unknown Error)",                /* 10083 */
  133.     "(Unknown Error)",                /* 10084 */
  134.     "(Unknown Error)",                /* 10085 */
  135.     "(Unknown Error)",                /* 10086 */
  136.     "(Unknown Error)",                /* 10087 */
  137.     "(Unknown Error)",                /* 10088 */
  138.     "(Unknown Error)",                /* 10089 */
  139.     "(Unknown Error)",                /* 10090 */
  140.     "Windows Sockets not ready",            /* 10091 */
  141.     "Windows Sockets version not supported",    /* 10092 */
  142.     "Windows Sockets not initialised",        /* 10093 */
  143.     "(Unknown Error)",                /* 10094 */
  144.     "(Unknown Error)",                /* 10095 */
  145.     "(Unknown Error)",                /* 10096 */
  146.     "(Unknown Error)",                /* 10097 */
  147.     "(Unknown Error)",                /* 10098 */
  148.     "(Unknown Error)",                /* 10099 */
  149. };
  150.  
  151. static    int    processable_functions[] =
  152. {
  153.         FALSE, /* BACKSPACE 0 */
  154.         FALSE, /* BACKWARD_CHARACTER 1 */
  155.         TRUE,  /* BACKWARD_HISTORY 2 */
  156.         FALSE, /* BACKWARD_WORD 3 */
  157.         FALSE, /* BEGINNING_OF_LINE 4 */
  158.         TRUE,  /* CLEAR_SCREEN 5 */
  159.         FALSE, /* COMMAND_COMPLETION 6 */
  160.         FALSE, /* DELETE_CHARACTER 7 */
  161.         FALSE, /* DELETE_NEXT_WORD 8 */
  162.         FALSE, /* DELETE_PREVIOUS_WORD 9 */
  163.         FALSE, /* END_OF_LINE 10 */
  164.         FALSE, /* ENTER_DIGRAPH 11 */
  165.         FALSE, /* ENTER_MENU 12 */
  166.         FALSE, /* ERASE_LINE 13 */
  167.         FALSE, /* ERASE_TO_BEG_OF_LINE 14 */
  168.         FALSE, /* ERASE_TO_END_OF_LINE 15 */
  169.         FALSE, /* FORWARD_CHARACTER 16 */
  170.         TRUE,  /* FORWARD_HISTORY 17 */
  171.         FALSE, /* FORWARD_WORD 18 */
  172.         FALSE, /* META1_CHARACTER 19 */
  173.         FALSE, /* META2_CHARACTER 20 */
  174.         FALSE, /* META3_CHARACTER 21 */
  175.         FALSE, /* META4_CHARACTER 22 */
  176.         TRUE,  /* NEXT_WINDOW 23 */
  177.         FALSE, /* NOTHING 24 */
  178.         TRUE,  /* PARSE_COMMAND 25 */
  179.         TRUE,  /* PREVIOUS_WINDOW 26 */
  180.         FALSE, /* QUIT_IRC 27 */
  181.         FALSE, /* QUOTE_CHARACTER 28 */
  182.         FALSE, /* REFRESH_INPUTLINE 29 */
  183.         FALSE, /* REFRESH_SCREEN 30 */
  184.         TRUE,  /* SCROLL_BACKWARD 31 */
  185.         TRUE,  /* SCROLL_END 32 */
  186.         TRUE,  /* SCROLL_FORWARD 33 */
  187.         TRUE,  /* SCROLL_START 34 */
  188.         FALSE, /* SELF_INSERT 35 */
  189.         TRUE,  /* SEND_LINE 36 */
  190.         FALSE, /* STOP_IRC 37 */
  191.         TRUE,  /* SWAP_LAST_WINDOW 38 */
  192.         TRUE,  /* SWAP_NEXT_WINDOW 39 */
  193.         TRUE,  /* SWAP_PREVIOUS_WINDOW 40 */
  194.         TRUE,  /* SWITCH_CHANNELS 41 */
  195.         FALSE, /* TOGGLE_INSERT_MODE 42 */
  196.         FALSE, /* TOGGLE_STOP_SCREEN 43 */
  197.         FALSE, /* TRANSPOSE_CHARACTERS 44 */
  198.         FALSE, /* TYPE_TEXT 45 */
  199.         TRUE,  /* UNSTOP_ALL_WINDOWS 46 */
  200.         FALSE  /* YANK_FROM_CUTBUFFER 47 */
  201. };
  202.  
  203. typedef struct    TermStru
  204. {
  205.     int    nLines;
  206.     int    nCols;
  207.     TermLine *ptl;
  208.     int    xPos;
  209.     int    yPos;
  210.     BOOL    bResized;
  211.     char    chAttrib;
  212.     int    iFlags;
  213. } Term;
  214.  
  215. #define    TF_CTRLDOWN    1
  216.  
  217. static    void    set_notifications()
  218. {
  219.     int    i;
  220.     long    nTimeout;
  221.  
  222.     FD_ZERO(&fdsServer);
  223.     FD_ZERO(&fdsDCC);
  224.     FD_ZERO(&fdsDCCWrite);
  225.  
  226.     set_server_bits(&fdsServer);
  227.     set_dcc_bits(&fdsDCC, &fdsDCCWrite);
  228.  
  229.     for (i = 0; i < fdsServer.fd_count; i++)
  230.     {
  231.         WSAAsyncSelect(    fdsServer.fd_array[i],
  232.                 hwndMain,
  233.                 WM_SOCKET,
  234.                 FD_READ | FD_CLOSE);
  235.     }
  236.     for (i = 0; i < fdsDCC.fd_count; i++)
  237.     {
  238.         WSAAsyncSelect(    fdsDCC.fd_array[i],
  239.                 hwndMain,
  240.                 WM_SOCKET,
  241.                 FD_ACCEPT | FD_READ | FD_CLOSE);
  242.     }
  243.     nTimeout = TimerTimeout();
  244.     if (nTimeout <= 60)
  245.         SetTimer(hwndMain, TIMER_SECOND, nTimeout * 1000, 0);
  246.     while (unhold_windows());
  247. }
  248.  
  249. static    void    process_socket(int s, int iEvent, int iError)
  250. {
  251.     if (FD_ISSET(s, &fdsBusy))
  252.         return;
  253.     FD_SET(s, &fdsBusy);
  254.     if (FD_ISSET(s, &fdsServer))
  255.     {
  256.         do_server(&fdsServer);
  257.     }
  258.     else if (FD_ISSET(s, &fdsDCC))
  259.     {
  260.         dcc_check(&fdsDCC);
  261.     }
  262.     FD_CLR(s, &fdsBusy);
  263.     set_notifications();
  264. }
  265.  
  266. static void get_font(void)
  267. {
  268.     LOGFONT    lf;
  269.     HDC    hdc;
  270.     TEXTMETRIC tm;
  271.     HFONT    hfontOld;
  272.     int    i;
  273.  
  274.     hdc = GetDC(GetDesktopWindow());
  275.  
  276.     GetTextMetrics(hdc, &tm);
  277.     cxChar = tm.tmAveCharWidth;
  278.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  279.  
  280.     lf.lfHeight = cyChar;
  281.     lf.lfWidth = cxChar;
  282.     lf.lfEscapement = 0;
  283.     lf.lfOrientation = 0;
  284.     lf.lfItalic = 0;
  285.     lf.lfStrikeOut = 0;
  286.     lf.lfCharSet = DEFAULT_CHARSET;
  287.     lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  288.     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  289.     lf.lfQuality = DEFAULT_QUALITY;
  290.     lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
  291.     strcpy(lf.lfFaceName, "System");
  292.     for (i = 0; i < 4; i++)
  293.     {
  294.         if (i & 2)
  295.             lf.lfWeight = FW_BOLD;
  296.         else
  297.             lf.lfWeight = FW_NORMAL;
  298.         if (i & 1)
  299.             lf.lfUnderline = 1;
  300.         else
  301.             lf.lfUnderline = 0;
  302.         hfontFixed[i] = CreateFontIndirect(&lf);
  303.     }
  304.  
  305.     hfontOld = (HFONT) SelectObject(hdc, (HGDIOBJ) hfontFixed[0]);
  306.     GetTextMetrics(hdc, &tm);
  307.     cxChar = tm.tmAveCharWidth;
  308.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  309.     SelectObject(hdc, (HGDIOBJ) hfontOld);
  310.  
  311.     ReleaseDC(GetDesktopWindow(), hdc);
  312.  
  313.     acrColours[0][0] = GetSysColor(COLOR_WINDOWTEXT);
  314.     acrColours[0][1] = GetSysColor(COLOR_WINDOW);
  315.     acrColours[1][0] = acrColours[0][1];
  316.     acrColours[1][1] = acrColours[0][0];
  317.     acrColours[2][0] = GetSysColor(COLOR_BTNTEXT);
  318.     acrColours[2][1] = GetSysColor(COLOR_BTNFACE);
  319.     acrColours[3][0] = GetSysColor(COLOR_CAPTIONTEXT);
  320.     acrColours[3][1] = acrColours[2][1];
  321. }
  322.  
  323. static    Term *new_mswindow(void)
  324. {
  325.     Term *pt;
  326.  
  327.     pt = (Term *) new_malloc(sizeof(Term));
  328.     pt->nLines = pt->nCols = pt->xPos = pt->yPos = 0;
  329.     pt->ptl = 0;
  330.     pt->chAttrib = 0;
  331.     pt->bResized = FALSE;
  332.     pt->iFlags = 0;
  333.     return pt;
  334. }
  335.  
  336. static    void    resize_line(TermLine *ptl, int nOld, int nNew)
  337. {
  338.     char    *pchText;
  339.     char    *pchAttribs;
  340.     int    iSmallest;
  341.  
  342.     if (nOld == nNew)
  343.         return;
  344.     if (nOld < nNew)
  345.         iSmallest = nOld;
  346.     else
  347.         iSmallest = nNew;
  348.     pchText = (char *) new_malloc(nNew);
  349.     pchAttribs = (char *) new_malloc(nNew);
  350.     memcpy(pchText, ptl->pchText, iSmallest);
  351.     memcpy(pchAttribs, ptl->pchAttribs, iSmallest);
  352.     memset(pchText + iSmallest, 32, nNew - iSmallest);
  353.     memset(pchAttribs + iSmallest, 0, nNew - iSmallest);
  354.     new_free(&ptl->pchText);
  355.     new_free(&ptl->pchAttribs);
  356.     ptl->pchAttribs = pchAttribs;
  357.     ptl->pchText = pchText;
  358. }
  359.  
  360. static    void    resize_window(Term *pt, int x, int y)
  361. {
  362.     TermLine *ptl;
  363.     int    i;
  364.     int    iSmallest;
  365.  
  366.     if (y < pt->nLines)
  367.         iSmallest = y;
  368.     else
  369.         iSmallest = pt->nLines;
  370.     if (y != pt->nLines)
  371.     {
  372.         ptl = (TermLine *) new_malloc(sizeof(TermLine) * y);
  373.         memcpy(ptl, pt->ptl, sizeof(TermLine) * iSmallest);
  374.         memset(ptl + iSmallest, 0, (y - iSmallest) * sizeof(TermLine));
  375.         for (i = iSmallest; i < pt->nLines; i++)
  376.         {
  377.             new_free(&pt->ptl[i].pchText);
  378.             new_free(&pt->ptl[i].pchAttribs);
  379.         }
  380.         new_free(&pt->ptl);
  381.         pt->ptl = ptl;
  382.         for (i = iSmallest; i < y; i++)
  383.             resize_line(pt->ptl + i, 0, x);
  384.     }
  385.     for (i = 0; i < iSmallest; i++)
  386.         resize_line(pt->ptl + i, pt->nCols, x);
  387.     pt->nLines = y;
  388.     pt->nCols = x;
  389.     if (pt->xPos >= pt->nCols)
  390.         pt->xPos = pt->nCols - 1;
  391.     if (pt->yPos >= pt->nLines)
  392.         pt->yPos = pt->nLines - 1;
  393. }
  394.  
  395.  
  396. static    void    char_to_window(Term *pt, char c, HWND hWnd)
  397. {
  398.     RECT    rcRedraw;
  399.  
  400.     switch(c)
  401.     {
  402.     case '\r':
  403.         pt->xPos = 0;
  404.         break;
  405.  
  406.     case '\n':
  407.         if (pt->yPos < pt->nLines - 1)
  408.             pt->yPos++;
  409.         break;
  410.  
  411.     case '\b':
  412.         if (pt->xPos > 0)
  413.             pt->xPos--;
  414.         break;
  415.  
  416.     default:
  417.         pt->ptl[pt->yPos].pchText[pt->xPos] = c;
  418.         pt->ptl[pt->yPos].pchAttribs[pt->xPos] = pt->chAttrib;
  419.         rcRedraw.left = pt->xPos * cxChar;
  420.         rcRedraw.right = rcRedraw.left + cxChar;
  421.         rcRedraw.top = pt->yPos * cyChar;
  422.         rcRedraw.bottom = rcRedraw.top + cyChar;
  423.         InvalidateRect(hWnd, &rcRedraw, TRUE);
  424.         if (pt->xPos < pt->nCols - 1)
  425.             pt->xPos++;
  426.     }
  427. }
  428.  
  429. Term *get_window_info(HWND hWnd)
  430. {
  431.     return (Term *) GetWindowLong(hWnd, 0);
  432. }
  433.  
  434. void    output_to_window(char *pchText, int iLen, HWND hwnd)
  435. {
  436.     Term *pt;
  437.  
  438.     pt = get_window_info(hwnd);
  439.     while (iLen--)
  440.         char_to_window(pt, *pchText++, hwnd);
  441. }
  442.  
  443. static void do_function(HWND hWnd, int iFunc, char *pchArg)
  444. {
  445.     Screen    *pscrOld, *pscrNew;
  446.     char    *pchLine;
  447.     int    iLen;
  448.  
  449.     pscrOld = current_screen;
  450.     for (pscrNew = screen_list;
  451.          pscrNew->hwnd != GetParent(hWnd);
  452.          pscrNew = pscrNew->next);
  453.     current_screen = pscrNew;
  454.     iLen = GetWindowTextLength(hWnd);
  455.     pchLine = (char *) new_malloc(iLen + 1);
  456.     GetWindowText(hWnd, pchLine, iLen + 1);
  457.     if (iFunc == SEND_LINE)
  458.     {
  459.         SetWindowText(hWnd, "");
  460.         last_input_screen = current_screen;
  461.     }
  462.     strmcpy(current_screen->input_buffer + current_screen->buffer_min_pos,
  463.         pchLine, INPUT_BUFFER_SIZE - current_screen->buffer_min_pos);
  464.     current_screen->buffer_pos = strlen(current_screen->input_buffer);
  465.     new_free(&pchLine);
  466.     key_names[iFunc].func(iFunc, pchArg);
  467.     set_current_screen(pscrOld);
  468.     set_notifications();
  469.     return 0;
  470. }
  471.  
  472. static    int    do_character(HWND hWnd, UINT wChar, BOOL bAlt)
  473. {
  474.     int    iFunc;
  475.     char    *pchArg;
  476.  
  477.     if (bAlt)
  478.     {
  479.         iFunc = meta1_keys[wChar].index;
  480.         pchArg = meta1_keys[wChar].stuff;
  481.     }
  482.     else
  483.     {
  484.         iFunc = keys[wChar].index;
  485.         pchArg = keys[wChar].stuff;
  486.     }
  487.     if (!processable_functions[iFunc])
  488.         return 0;
  489.     else
  490.     {
  491.         do_function(hWnd, iFunc, pchArg);
  492.         return 1;
  493.     }
  494. }
  495.  
  496. LRESULT CALLBACK _export edit_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  497. {
  498.     Term *pt;
  499.  
  500.     if (wMsg == WM_KEYDOWN)
  501.     {
  502.         pt = get_window_info(GetParent(hWnd));
  503.         switch(wParam)
  504.         {
  505.         case VK_NEXT:
  506.             do_function(hWnd, SCROLL_FORWARD, 0);
  507.             return 0;
  508.  
  509.         case VK_PRIOR:
  510.             do_function(hWnd, SCROLL_BACKWARD, 0);
  511.             return 0;
  512.  
  513.         case VK_HOME:
  514.             if (pt->iFlags & TF_CTRLDOWN)
  515.             {
  516.                 do_function(hWnd, SCROLL_START, 0);
  517.                 return 0;
  518.             }
  519.             break;
  520.  
  521.         case VK_END:
  522.             if (pt->iFlags & TF_CTRLDOWN)
  523.             {
  524.                 do_function(hWnd, SCROLL_END, 0);
  525.                 return 0;
  526.             }
  527.             break;
  528.  
  529.         case VK_UP:
  530.             do_function(hWnd, BACKWARD_HISTORY, 0);
  531.             return 0;
  532.  
  533.         case VK_DOWN:
  534.             do_function(hWnd, FORWARD_HISTORY, 0);
  535.             return 0;
  536.  
  537.         case VK_CONTROL:
  538.             pt->iFlags |= TF_CTRLDOWN;
  539.             break;
  540.         }
  541.     }
  542.     else if (wMsg == WM_KEYUP && wParam == VK_CONTROL)
  543.     {
  544.         pt = get_window_info(GetParent(hWnd));
  545.         pt->iFlags &= ~TF_CTRLDOWN;
  546.     }
  547.     else if (wMsg == WM_CHAR)
  548.     {
  549.         if (lParam & 0x20000000 &&
  550.             wParam >= 0 &&
  551.             wParam <= 255)
  552.         {
  553.             if (do_character(hWnd, wParam, TRUE))
  554.                 return 0;
  555.         }
  556.         
  557.         /* Allow binding of control characters other than
  558.          * backspace, ^C, ^V, and ^X, plus meta1-anything,
  559.          * which becomes ALT-X
  560.          */
  561.         if (wParam >= 0 &&
  562.             wParam < 32 &&
  563.             wParam != 8 &&
  564.             wParam != 3 &&
  565.             wParam != 24 &&
  566.             wParam != 22)
  567.         {
  568.             if (do_character(hWnd, wParam, FALSE))
  569.                 return 0;
  570.         }
  571.     }
  572.     return CallWindowProc((FARPROC) old_edit_window_proc, hWnd, wMsg, wParam, lParam);
  573. }
  574.  
  575. LRESULT CALLBACK _export child_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  576. {
  577.     Term *pt;
  578.     RECT    rcClient;
  579.     int    i, j;
  580.     int    xStart, xEnd;
  581.     PAINTSTRUCT    ps;
  582.     char    *pchNull;
  583.     HWND    hwndEdit;
  584.     HFONT    hfontOld;
  585.     char    chAttrib;
  586.     Screen    *pscrOld, *pscrNew;
  587.  
  588.     switch(wMsg)
  589.     {
  590.     case WM_CREATE:
  591.         pt = new_mswindow();
  592.         SetWindowLong(hWnd, 0, (LONG) pt);
  593.         GetClientRect(hWnd, &rcClient);
  594.         hwndEdit = CreateWindow(    "EDIT",
  595.                         "",
  596.                         WS_CHILD |
  597.                          WS_HSCROLL |
  598.                          WS_VISIBLE |
  599.                          ES_AUTOHSCROLL,
  600.                         0, rcClient.bottom - cyChar,
  601.                         rcClient.right, cyChar,
  602.                         hWnd,
  603.                         0,
  604.                         hInstance,
  605.                         0);
  606.         if (!old_edit_window_proc)
  607.             old_edit_window_proc = (WNDPROC) GetWindowLong(hwndEdit, GWL_WNDPROC);
  608.         SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG) edit_window_proc);        
  609.         break;
  610.  
  611.     case WM_SIZE:
  612.         if (wParam != SIZE_MINIMIZED)
  613.         {
  614.             pt = get_window_info(hWnd);
  615.             GetClientRect(hWnd, &rcClient);
  616.             resize_window(pt, rcClient.right / cxChar, rcClient.bottom / cyChar);
  617.             MoveWindow(GetDlgItem(hWnd, 0), 0, rcClient.bottom - cyChar,
  618.                             rcClient.right, cyChar, TRUE);
  619.  
  620.             pscrOld = current_screen;
  621.             for (pscrNew = screen_list;
  622.                  pscrNew && pscrNew->hwnd != hWnd;
  623.                  pscrNew = pscrNew->next);
  624.             if (pscrNew)
  625.             {
  626.                 current_screen = pscrNew;
  627.                 pt->bResized = TRUE;
  628.                 refresh_screen();
  629.             }
  630.             if (pscrOld)
  631.                 set_current_screen(pscrOld);
  632.             else
  633.                 current_screen = 0;
  634.         }
  635.         break;
  636.  
  637.     case WM_MDIACTIVATE:
  638.         SetFocus(GetDlgItem(hWnd, 0));
  639.         break;
  640.  
  641.     case WM_PAINT:
  642.         pt = get_window_info(hWnd);
  643.         BeginPaint(hWnd, &ps);
  644.         hfontOld = (HFONT) SelectObject(ps.hdc, (HGDIOBJ) hfontFixed[0]);
  645.         for (i = 0; i < pt->nLines; i++)
  646.         {
  647.             xStart = 0;
  648.             while (xStart < pt->nCols && pt->ptl[i].pchText[xStart])
  649.             {
  650.                 xEnd = xStart;
  651.                 chAttrib = pt->ptl[i].pchAttribs[xStart];
  652.                 while (++xEnd < pt->nCols &&
  653.                        pt->ptl[i].pchText[xEnd] &&
  654.                        pt->ptl[i].pchAttribs[xEnd] == chAttrib);
  655.                 SelectObject(ps.hdc, (HGDIOBJ) hfontFixed[chAttrib & AT_FONTFLAGS]);
  656.                 SetTextColor(ps.hdc, acrColours[(chAttrib & AT_COLOURFLAGS) >> AT_COLOURSHIFT][0]);
  657.                 SetBkColor(ps.hdc, acrColours[(chAttrib & AT_COLOURFLAGS) >> AT_COLOURSHIFT][1]);
  658.                 TextOut(ps.hdc, cxChar * xStart, cyChar * i, pt->ptl[i].pchText + xStart, xEnd - xStart);
  659.                 xStart = xEnd;
  660.             }
  661.         }
  662.         SelectObject(ps.hdc, (HGDIOBJ) hfontOld);
  663.         EndPaint(hWnd, &ps);
  664.         return 0;
  665.  
  666.     case WM_CLOSE:
  667.         pscrOld = current_screen;
  668.         for (pscrNew = screen_list;
  669.              pscrNew && pscrNew->hwnd != hWnd;
  670.              pscrNew = pscrNew->next);
  671.         if (pscrNew)
  672.             kill_screen(pscrNew);
  673.         if (pscrOld)
  674.             set_current_screen(pscrOld);
  675.         else
  676.             current_screen = 0;
  677.         break;
  678.     }
  679.     return DefMDIChildProc(hWnd, wMsg, wParam, lParam);
  680. }
  681.  
  682. LRESULT CALLBACK _export main_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  683. {
  684.     LRESULT    iValue;
  685.  
  686.     switch(wMsg)
  687.     {
  688.     case WM_SOCKET:
  689.         process_socket(wParam,
  690.                   WSAGETSELECTEVENT(lParam),
  691.                   WSAGETSELECTERROR(lParam));
  692.         return 0;
  693.  
  694.     case WM_SETFOCUS:
  695.         iValue = SendMessage(hwndMDI, WM_MDIGETACTIVE, 0, 0L);
  696.         SetFocus(GetDlgItem((HWND) LOWORD(iValue), 0));
  697.         break;
  698.  
  699.     case WM_CLOSE:
  700.         e_quit("QUIT", "Closed main window");
  701.         break;
  702.  
  703.     case WM_TIMER:
  704.         switch(wParam)
  705.         {
  706.         case TIMER_MINUTE:
  707.             if (get_int_var(CLOCK_VAR))
  708.             {
  709.                 status_update(1);
  710.                 cursor_to_input();
  711.             }
  712.             do_notify();
  713.             break;
  714.  
  715.         case TIMER_SECOND:
  716.             KillTimer(hWnd, TIMER_SECOND);
  717.             ExecuteTimers();
  718.             break;
  719.         }
  720.         set_notifications();
  721.         break;
  722.  
  723.     case WM_COMMAND:
  724.         switch(wParam)
  725.         {
  726.         case 101:
  727.             e_quit("QUIT", "Selected exit option on menu");
  728.             break;
  729.  
  730.         case 201:
  731.             SendMessage(hwndMDI, WM_MDITILE, MDITILE_VERTICAL, 0);
  732.             break;
  733.  
  734.         case 202:
  735.             SendMessage(hwndMDI, WM_MDITILE, MDITILE_HORIZONTAL, 0);
  736.             break;
  737.  
  738.         case 203:
  739.             SendMessage(hwndMDI, WM_MDICASCADE, 0, 0);
  740.             break;
  741.  
  742.         case 204:
  743.             SendMessage(hwndMDI, WM_MDIICONARRANGE, 0, 0);
  744.             break;
  745.         }
  746.         break;
  747.     }
  748.  
  749.     if (hwndMDI)
  750.         return DefFrameProc(hWnd, hwndMDI, wMsg, wParam, lParam);
  751.     else
  752.         return DefWindowProc(hWnd, wMsg, wParam, lParam);
  753. }
  754.  
  755. int PASCAL WinMain(HANDLE hInstance_, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  756. {
  757.     WNDCLASS    wc;
  758.     RECT        rcClient;
  759.     MSG        msg;
  760.     CLIENTCREATESTRUCT ccs;
  761.     WSADATA        wsad;
  762.     char        *argv[3];
  763.     MODULEENTRY me;
  764.     TASKENTRY te;
  765.  
  766.     memset(&te, 0, sizeof(te));
  767.     te.dwSize = sizeof(te);
  768.     TaskFindHandle(&te, GetCurrentTask());
  769.     memset(&me, 0, sizeof(me));
  770.     me.dwSize = sizeof(me);
  771.     ModuleFindHandle(&me, te.hModule);
  772.     *strrchr(me.szExePath, '\\') = 0;
  773.     malloc_strcpy(&pchPath, me.szExePath);
  774.  
  775.     hInstance = hInstance_;
  776.  
  777.     switch(WSAStartup(0x0101, &wsad))
  778.     {
  779.     case 0:
  780.         if (wsad.wVersion != 0x0101)
  781.         {
  782.             MessageBox(0, "Your Windows Sockets version is too new", 0, MB_OK);
  783.             exit(1);
  784.         }
  785.         break;
  786.  
  787.     case WSAVERNOTSUPPORTED:
  788.         MessageBox(0, "Windows Sockets 1.1 is required", 0, MB_OK);
  789.         exit(1);
  790.         break;
  791.  
  792.     case WSASYSNOTREADY:
  793.         MessageBox(0, "Windows Sockets is not ready", 0, MB_OK);
  794.         exit(1);
  795.         break;
  796.  
  797.     default:
  798.         MessageBox(0, "Could not initialise Windows Sockets", 0, MB_OK);
  799.         exit(1);
  800.         break;
  801.     }
  802.  
  803.     get_font();
  804.  
  805.     memset(&wc, 0, sizeof(wc));
  806.     wc.hInstance = hInstance;
  807.     wc.hIcon = LoadIcon(hInstance, "IRC_ICO");
  808.     wc.hCursor = LoadCursor(0, IDC_ARROW);
  809.     wc.hbrBackground = COLOR_WINDOW + 1;
  810.     wc.lpszClassName = "IRCII Main Window";
  811.     wc.lpszMenuName = "MAIN_MNU";
  812.     wc.lpfnWndProc = main_window_proc;
  813.     RegisterClass(&wc);
  814.  
  815.     wc.lpfnWndProc = child_window_proc;
  816.     wc.lpszClassName = "IRCII Child Window";
  817.     wc.lpszMenuName = 0;
  818.     wc.cbWndExtra = sizeof(void *);
  819.     RegisterClass(&wc);
  820.  
  821.     hwndMain = CreateWindow(    "IRCII Main Window",
  822.                     "IRC II for Windows",
  823.                     WS_OVERLAPPEDWINDOW |
  824.                      WS_VISIBLE,
  825.                     CW_USEDEFAULT,
  826.                     nCmdShow,
  827.                     CW_USEDEFAULT,
  828.                     0,
  829.                     0,
  830.                     0,
  831.                     hInstance,
  832.                     0);
  833.  
  834.     GetClientRect(hwndMain, &rcClient);
  835.  
  836.     ccs.hWindowMenu = GetSubMenu(GetMenu(hwndMain), 1);
  837.     ccs.idFirstChild = 1000;
  838.  
  839.     hwndMDI = CreateWindow(        "MDICLIENT",
  840.                     "IRC II MDI Window",
  841.                     WS_CLIPCHILDREN |
  842.                      WS_CHILD |
  843.                      WS_HSCROLL |
  844.                      WS_VSCROLL |
  845.                      WS_VISIBLE,
  846.                     0, 0,
  847.                     rcClient.right, rcClient.bottom,
  848.                     hwndMain,
  849.                     0,
  850.                     hInstance,
  851.                     &ccs);
  852.  
  853.     build_status();
  854.     argv[0] = "ircii";
  855.     argv[1] = lpCmdLine;
  856.     argv[2] = 0;
  857.     old_main(2, argv);
  858.     current_screen = screen_list;
  859.     set_notifications();
  860.  
  861.     SetTimer(hwndMain, TIMER_MINUTE, 60000, 0);
  862.     while (GetMessage(&msg, 0, 0, 0))
  863.     {
  864.         TranslateMessage(&msg);
  865.         DispatchMessage(&msg);
  866.     }
  867.     DeleteObject((HGDIOBJ) hfontFixed);
  868.     WSACleanup();
  869. }
  870.  
  871.  
  872. int
  873. getpid(void)
  874. {
  875.     return (int) hInstance;
  876. }
  877.  
  878. int
  879. getppid(void)
  880. {
  881.     return 1;
  882. }
  883.  
  884. void execcmd(void)
  885. {
  886.     yell("EXEC is not available under Windows");
  887. }
  888.  
  889. void    win_create_window(Screen *pscr)
  890. {
  891.     MDICREATESTRUCT mdic;
  892.     char    achNumber[40];
  893.     static    int    nWindow = 0;
  894.  
  895.     mdic.szClass = "IRCII Child Window";
  896.     sprintf(achNumber, "Window %d", ++nWindow);
  897.     mdic.szTitle = achNumber;
  898.     mdic.hOwner = hInstance;
  899.     mdic.x = CW_USEDEFAULT;
  900.     mdic.y = CW_USEDEFAULT;
  901.     mdic.cx = CW_USEDEFAULT;
  902.     mdic.cy = CW_USEDEFAULT;
  903.     mdic.style = 0;
  904.     mdic.lParam = 0;
  905.     pscr->hwnd = (HWND) SendMessage(hwndMDI, WM_MDICREATE, 0, (LPARAM) &mdic);
  906. }
  907.  
  908. void
  909. term_beep(void)
  910. {
  911.     MessageBeep(0);
  912. }
  913.  
  914. void
  915. term_move_cursor(int x, int y)
  916. {
  917.     Term *pt;
  918.  
  919.     pt = get_window_info(current_screen->hwnd);
  920.     pt->xPos = x;
  921.     pt->yPos = y;
  922.     if (pt->xPos >= pt->nCols)
  923.         pt->xPos = pt->nCols - 1;
  924.     if (pt->yPos >= pt->nLines)
  925.         pt->yPos = pt->nLines - 1;
  926. }
  927.  
  928. void
  929. term_cr(void)
  930. {
  931.     Term *pt;
  932.  
  933.     pt = get_window_info(current_screen->hwnd);
  934.     pt->xPos = 0;
  935. }
  936.  
  937. void
  938. term_newline(void)
  939. {
  940.     Term *pt;
  941.  
  942.     pt = get_window_info(current_screen->hwnd);
  943.     if (pt->yPos < pt->nLines - 1)
  944.         pt->yPos++;
  945. }
  946.  
  947. int    term_scroll(int yStart, int yEnd, int yScroll)
  948. {
  949.     Term *pt;
  950.     TermLine *ptl;
  951.     BOOL    bNegative = FALSE;
  952.     int    i;
  953.     RECT    rcScroll;
  954.  
  955.     if (yScroll == 0)
  956.         return 1;
  957.     if (yScroll < 0)
  958.     {
  959.         bNegative = TRUE;
  960.         yScroll = -yScroll;
  961.     }
  962.     pt = get_window_info(current_screen->hwnd);
  963.     if (yStart < 0)
  964.         yStart = 0;
  965.     if (yEnd >= pt->nLines)
  966.         yEnd = pt->nLines - 1;
  967.     if (yScroll >= yEnd - yStart + 1)
  968.         yScroll = yEnd - yStart + 1;
  969.     ptl = (TermLine *) new_malloc(sizeof(TermLine) * yScroll);
  970.     if (bNegative)
  971.     {
  972.         memcpy(ptl, pt->ptl + yEnd + 1 - yScroll, sizeof(TermLine) * yScroll);
  973.         memmove(pt->ptl + yStart + yScroll, pt->ptl + yStart, (yEnd - yStart + 1 - yScroll) * sizeof(TermLine));
  974.         memcpy(pt->ptl + yStart, ptl, sizeof(TermLine) * yScroll);
  975.         for (i = yStart; i < yStart + yScroll; i++)
  976.         {
  977.             memset(pt->ptl[i].pchText, 32, pt->nCols);
  978.             memset(pt->ptl[i].pchAttribs, 0, pt->nCols);
  979.         }
  980.     }
  981.     else
  982.     {
  983.         memcpy(ptl, pt->ptl + yStart, sizeof(TermLine) * yScroll);
  984.         memmove(pt->ptl + yStart, pt->ptl + yStart + yScroll, (yEnd - yStart + 1 - yScroll) * sizeof(TermLine));
  985.         memcpy(pt->ptl + yEnd + 1 - yScroll, ptl, sizeof(TermLine) * yScroll);
  986.         for (i = yEnd + 1 - yScroll; i <= yEnd; i++)
  987.         {
  988.             memset(pt->ptl[i].pchText, 32, pt->nCols);
  989.             memset(pt->ptl[i].pchAttribs, 0, pt->nCols);
  990.         }
  991.     }
  992.     new_free(&ptl);
  993.     GetClientRect(current_screen->hwnd, &rcScroll);
  994.     rcScroll.top = cyChar * yStart;
  995.     rcScroll.bottom = cyChar * (yEnd + 1);
  996.     ScrollWindow(current_screen->hwnd, 0, cyChar * yScroll * (bNegative ? 1 : -1), &rcScroll, &rcScroll);
  997.     return 1;
  998. }
  999.  
  1000. #define    AT_BOLD        2
  1001. #define    AT_INVERSE    4
  1002. #define    AT_STATUS    8
  1003.  
  1004. void term_underline_on(void)
  1005. {
  1006.     Term *pt;
  1007.  
  1008.     pt = get_window_info(current_screen->hwnd);
  1009.     pt->chAttrib |= AT_USCORE;
  1010. }
  1011.  
  1012. void term_underline_off(void)
  1013. {
  1014.     Term *pt;
  1015.  
  1016.     pt = get_window_info(current_screen->hwnd);
  1017.     pt->chAttrib &= ~AT_USCORE;
  1018. }
  1019.  
  1020. void term_standout_on(void)
  1021. {
  1022.     Term *pt;
  1023.  
  1024.     pt = get_window_info(current_screen->hwnd);
  1025.     pt->chAttrib |= AT_INVERSE;
  1026. }
  1027.  
  1028. void term_standout_off(void)
  1029. {
  1030.     Term *pt;
  1031.  
  1032.     pt = get_window_info(current_screen->hwnd);
  1033.     pt->chAttrib &= ~AT_INVERSE;
  1034. }
  1035.  
  1036. void term_bold_on(void)
  1037. {
  1038.     Term *pt;
  1039.  
  1040.     pt = get_window_info(current_screen->hwnd);
  1041.     pt->chAttrib |= AT_BOLD;
  1042. }
  1043.  
  1044. void term_bold_off(void)
  1045. {
  1046.     Term *pt;
  1047.  
  1048.     pt = get_window_info(current_screen->hwnd);
  1049.     pt->chAttrib &= ~AT_BOLD;
  1050. }
  1051.  
  1052. void term_status_on(void)
  1053. {
  1054.     Term *pt;
  1055.  
  1056.     pt = get_window_info(current_screen->hwnd);
  1057.     pt->chAttrib |= AT_STATUS;
  1058. }
  1059.  
  1060. void term_status_off(void)
  1061. {
  1062.     Term *pt;
  1063.  
  1064.     pt = get_window_info(current_screen->hwnd);
  1065.     pt->chAttrib &= ~AT_STATUS;
  1066. }
  1067.  
  1068.  
  1069. int term_clear_screen(void)
  1070. {
  1071.     int    i;
  1072.     Term *pt;
  1073.  
  1074.     if (!current_screen)
  1075.         return 0;
  1076.     pt = get_window_info(current_screen->hwnd);
  1077.     for (i = 0; i < pt->nLines; i++)
  1078.     {
  1079.         memset(pt->ptl[i].pchText, 32, pt->nCols);
  1080.         memset(pt->ptl[i].pchAttribs, pt->chAttrib, pt->nCols);
  1081.     }
  1082.     InvalidateRect(current_screen->hwnd, 0, TRUE);
  1083.     return 0;
  1084. }
  1085.  
  1086. int term_clear_to_eol(void)
  1087. {
  1088.     Term *pt;
  1089.     RECT    rcRedraw;
  1090.  
  1091.     pt = get_window_info(current_screen->hwnd);
  1092.     memset(pt->ptl[pt->yPos].pchText + pt->xPos, 32, pt->nCols - pt->xPos);
  1093.     memset(pt->ptl[pt->yPos].pchAttribs + pt->xPos, pt->chAttrib, pt->nCols - pt->xPos);
  1094.     rcRedraw.top = pt->yPos * cyChar;
  1095.     rcRedraw.bottom = rcRedraw.top + cyChar;
  1096.     rcRedraw.left = pt->xPos * cxChar;
  1097.     rcRedraw.right = pt->nCols * cxChar;
  1098.     InvalidateRect(current_screen->hwnd, &rcRedraw, TRUE);
  1099.     return 0;
  1100. }
  1101.  
  1102. int term_space_erase(int nChars)
  1103. {
  1104.     Term *pt;
  1105.     RECT rcRedraw;
  1106.  
  1107.     pt = get_window_info(current_screen->hwnd);
  1108.     if (nChars > pt->nCols - pt->xPos)
  1109.         nChars = pt->nCols - pt->xPos;
  1110.     memset(pt->ptl[pt->yPos].pchText + pt->xPos, 32, nChars);
  1111.     memset(pt->ptl[pt->yPos].pchAttribs + pt->xPos, pt->chAttrib, nChars);
  1112.     rcRedraw.top = pt->yPos * cyChar;
  1113.     rcRedraw.bottom = rcRedraw.top + cyChar;
  1114.     rcRedraw.left = pt->xPos * cxChar;
  1115.     rcRedraw.right = pt->nCols * cxChar;
  1116.     InvalidateRect(current_screen->hwnd, &rcRedraw, TRUE);
  1117.     return 0;
  1118. }
  1119.  
  1120. int term_delete(void)
  1121. {
  1122.     Term *pt;
  1123.     RECT rcScroll;
  1124.  
  1125.     pt = get_window_info(current_screen->hwnd);
  1126.     memmove(pt->ptl[pt->yPos].pchText + pt->xPos,
  1127.         pt->ptl[pt->yPos].pchText + pt->xPos + 1,
  1128.         pt->nCols = pt->xPos + 1);
  1129.     memmove(pt->ptl[pt->yPos].pchAttribs + pt->xPos,
  1130.         pt->ptl[pt->yPos].pchAttribs + pt->xPos + 1,
  1131.         pt->nCols = pt->xPos + 1);
  1132.     pt->ptl[pt->yPos].pchText[pt->nCols - 1] = ' ';
  1133.     pt->ptl[pt->yPos].pchAttribs[pt->nCols - 1] = pt->chAttrib;
  1134.     rcScroll.top = pt->yPos * cyChar;
  1135.     rcScroll.bottom = rcScroll.top + cyChar;
  1136.     rcScroll.left = pt->xPos * cxChar;
  1137.     rcScroll.right = pt->nCols * cxChar;
  1138.     ScrollWindow(current_screen->hwnd, -cxChar, cyChar, &rcScroll, &rcScroll);
  1139.     return 0;
  1140. }
  1141.  
  1142.  
  1143. int term_get_columns(void)
  1144. {
  1145.     Term *pt;
  1146.     RECT rcRedraw;
  1147.  
  1148.     if (!current_screen)
  1149.         return 80;
  1150.     pt = get_window_info(current_screen->hwnd);
  1151.     return pt->nCols;
  1152. }
  1153.  
  1154. int term_get_rows(void)
  1155. {
  1156.     Term *pt;
  1157.     RECT rcRedraw;
  1158.  
  1159.     if (!current_screen)
  1160.         return 80;
  1161.     pt = get_window_info(current_screen->hwnd);
  1162.     return pt->nLines;
  1163. }
  1164.  
  1165. int term_flush(void)
  1166. {
  1167.     UpdateWindow(current_screen->hwnd);
  1168. }
  1169.  
  1170. int term_resize(void)
  1171. {
  1172.     Term *pt;
  1173.     RECT rcRedraw;
  1174.     BOOL bResized;
  1175.  
  1176.     if (!current_screen)
  1177.         return 0;
  1178.     pt = get_window_info(current_screen->hwnd);
  1179.     bResized = pt->bResized;
  1180.     pt->bResized = 0;
  1181.     return bResized;
  1182. }
  1183.  
  1184. void
  1185. set_input(str)
  1186.     char    *str;
  1187. {
  1188.     Term *pt;
  1189.     int    iLen;
  1190.  
  1191.     pt = get_window_info(current_screen->hwnd);
  1192.     SetWindowText(GetDlgItem(current_screen->hwnd, 0), str);
  1193.     iLen = strlen(str);
  1194.     SendMessage(GetDlgItem(current_screen->hwnd, 0), EM_SETSEL, 0,
  1195.             MAKELPARAM(iLen, iLen));
  1196. }
  1197.  
  1198. char    *
  1199. get_input()
  1200. {
  1201.     return (&(current_screen->input_buffer[current_screen->buffer_min_pos]));
  1202. }
  1203.  
  1204.  
  1205. char    *
  1206. get_path(int iVal)
  1207. {
  1208.     static    char    FAR buffer[BIG_BUFFER_SIZE];
  1209.  
  1210.     strcpy(buffer, pchPath);
  1211.     switch(iVal)
  1212.     {
  1213.     case 0:    /* Irc Lib (with trailing slash) */
  1214.         strcat(buffer, "/LIB/");
  1215.         break;
  1216.  
  1217.     case 1: /* Help Path */
  1218.         strcat(buffer, "/HELP");
  1219.         break;
  1220.  
  1221.     case 2: /* Translation Path */
  1222.         strcat(buffer, "/TRANSLAT");
  1223.         break;
  1224.  
  1225.     case 3: /* Load Path */
  1226.         strcat(buffer, "/SCRIPTS");
  1227.         break;
  1228.  
  1229.     case 4: /* IRC directory */
  1230.         break;
  1231.     }
  1232.     return buffer;
  1233. }
  1234.